#include "helper.h"

#include "../include/mutex.h"


namespace mix
{

Mutex::Mutex() {
#ifdef M_WIN
    ::InitializeCriticalSection( &_mutex);
#else
    int ret = ::pthread_mutex_init( &_mutex, NULL);
    if ( ret)
        MIX_LOG( LOG_CRITICAL, "pthread_mutex_init failed.[code: %d]", ret);
#endif
}

Mutex::~Mutex(){
#ifdef M_WIN
    DeleteCriticalSection( &_mutex);
#else
	pthread_mutex_destroy( &_mutex);
#endif
}

void Mutex::lock(){
#ifdef M_WIN
    EnterCriticalSection( &_mutex);
#else
	int r = pthread_mutex_lock( &_mutex);
	if ( r == ENOMEM)
		MIX_LOG( 0, "Mutex::lock ENOMEM, error code=", r);
	else ( r == EDEADLK)
		MIX_LOG( 4, "%s", "Mutex::lock Dead Lock");
#endif
}

void Mutex::unlock(){
#ifdef M_WIN
    LeaveCriticalSection( &_mutex);
#else
	pthread_mutex_unlock( &_mutex);
#endif
}

bool Mutex::tryLock() {
#ifdef M_WIN
    if ( TryEnterCriticalSection( &_mutex))
        return true;
    else
        return false;
#else
	if ( pthread_mutex_trylock( &_mutex))
		return false;
	else
		return true;
#endif
}

bool Mutex::tryLock( long msec) {
#ifdef M_WIN
    if ( tryLock())
        return true;
    time_t startTime, curTime;
    time( &startTime);
    ::Sleep( 0);

    while ( true) {
        if ( tryLock())
            return true;
        time( &curTime);
        if ( (curTime - startTime) * 1000 >= msec)
            return false;
        ::Sleep( 0);
    }
    return false;
#else
    struct timespec ts;
    if ( !futureAbsTime( msec, ts))
        return false;
    
    if ( pthread_mutex_timedlock( &_mutex, &ts))
        return false;
    else
        return true;    
#endif
}

void* Mutex::getNative() {
	return &_mutex;
}

}	// namespace mix
